﻿#ifndef CARPLAY_EXT_H
#define CARPLAY_EXT_H

#include <iostream>
#include <cassert>
#include <string>
#include <vector>

typedef int		CarplayEntity;
#define CarplayEntity_NotApplicable			0
#define CarplayEntity_Controller			1
#define CarplayEntity_Accessory				2

typedef int		CarplayTransferType;
#define CarplayTransferType_NotApplicable				0
#define CarplayTransferType_Take						1 // Transfer ownership permanently.
#define CarplayTransferType_Untake						2 // Release permanent ownership.
#define CarplayTransferType_Borrow						3 // Transfer ownership temporarily.
#define CarplayTransferType_Unborrow					4 // Release temporary ownership.


typedef int		CarplayTransferPriority;
#define CarplayTransferPriority_NotApplicable				0
#define CarplayTransferPriority_NiceToHave					100 // Transfer succeeds only if constraint is <= Anytime.
#define CarplayTransferPriority_UserInitiated				500 // Transfer succeeds only if constraint is <= UserInitiated.


typedef int		CarplayConstraint;
#define CarplayConstraint_NotApplicable			0
#define CarplayConstraint_Anytime					100  // Resource may be taken/borrowed at any time.
#define CarplayConstraint_UserInitiated			500  // Resource may be taken/borrowed if user initiated.
#define CarplayConstraint_Never					1000 // Resource may never be taken/borrowed.


typedef int		CarplayTriState;
#define CarplayTriState_NotApplicable		0
#define CarplayTriState_False				-1
#define CarplayTriState_True				1


typedef int		CarplaySpeechMode;
#define CarplaySpeechMode_NotApplicable			0
#define CarplaySpeechMode_None						-1 // No speech-related states are active.
#define CarplaySpeechMode_Speaking					1  // Device is speaking to the user.
#define CarplaySpeechMode_Recognizing				2  // Device is recording audio to recognize speech from the user.

typedef struct
{
    CarplayEntity			entity;
    CarplaySpeechMode		mode;

}	CarPlaySpeechState;

typedef struct
{
    CarplayEntity			screen;		// Owner of the screen.
    CarplayEntity			mainAudio;	// Owner of main audio.
    CarplayEntity			phoneCall;	// Owner of phone call.
    CarPlaySpeechState		speech;		// Owner of speech and its mode.
    CarplayEntity			turnByTurn;	// Owner of navigation.

} CarPlayModeState;

typedef enum
{
	UsbHost = 0,
	UsbDevice
} UsbMode;

typedef enum
{
    AudioStreamMedia = 0, // 音乐
	AudioStreamCall,		// 电话
	AudioStreamRECOGNITION, // siri
    AudioStreamAlt,      // 辅助音,包括导航音,系统提示音
    AudioStreamRec,		 // 录音
    AudioStreamAlert
} UserAudioStreamType;

class SdCarplay;
class ICarplayCallbacks
{
public:
    virtual void iap2LinkStatus(int status) {
        
    }
    
    virtual int iap2WriteData(char *buf, int len) {
    	
    }

    virtual void carplaySessionStart() {

    }

    virtual void carplaySessionStop() {

    }

	virtual int switchUsbModeCB(UsbMode mode) = 0;

    virtual void appleTimeUpdateCB(long long time) = 0;
    
    virtual void appleLanguageUpdateCB(const char *lang) = 0;
    
    virtual void appleCallStateUpdateCB(const char *remoteId,
										const char *displayName,
										int status,
										int direction,
										const char *uuid,
										const char *addrBookId,
										const char *label,
										int service) = 0;

    virtual void NotifyDeviceNameCB(const char *name, int name_len) = 0;
    
    /* *
     * @brief 退出的通知
     * */
    virtual void carplayExitCB() = 0;
    /* *
     * @brief 点击返回本地界面的按钮通知
     * */
    virtual void returnNativeUICB() = 0;
    /* *
     * @brief carplay模式改变的通知
     * */
    virtual void modesChangeCB(CarPlayModeState *modes) = 0;
    /* *
     * @brief carplay禁止蓝牙
     * */
	virtual void disableBluetoothCB() = 0;

	/* *
     * @brief 压低其他音频流音量
     * */
    virtual void caplayDuckAudioCB(double inDurationSecs, double inVolume) = 0;
    /* *
     * @brief 还原其他音频流音量
     * */
    virtual void caplayUnduckAudioCB(double inDurationSecs) = 0;
	
	 /* *
     * @brief 音频流开始
     * @param 			handle 		该路音频流的操作句柄,要缓存起来,作为playStream/recordStream的第一个参数
     * @param			type  		音频流类型
     * @param 			rate		音频的采样率
     * @param 			bits		音频位宽
     * @param 			channels	音频通道数
     * */
    virtual void carplayAudioStartCB(int handle, UserAudioStreamType type, int rate, int bits, int channels) = 0;
    /* *
     * @brief 音频流停止
     * */
    virtual void carplayAudioStopCB(int handle, UserAudioStreamType type) = 0;
    
    /* *
     * @brief 视频流开始
     * */
    virtual int carplayVideoStartCB() = 0;
    /* *
     * @brief 视频流停止
     * */
    virtual void carplayVideoStopCB() = 0;
     /* *
     * @brief 视频流数据处理
     * */
    virtual int carplayVideoDataProcCB(const char *buf, int len) = 0;
};

class SdCarplay
{
public:
    enum CarplayState {
        CarplayStateInit             = -1, // carplay处于初始状态
        CarplayStateConnecting       = 0,  // carplay正在连接中
        CarplayStateShow             = 1,  // carplay前台显示
        CarplayStateHide             = 2,  // carplay已经连接上,但处于后台隐藏
        CarplayStateExit             = 3   // carplay退出
    };

    enum InitialMode {
        ModeNone = -1,
        Mode0 = 0, //video autimatically start;
        Mode1 = 1, //video autimatically start;audio don't start autimatically
    };

    enum AppleUIApp
    {
        AppleUIAppNomal = 0, //回到carplay正常主界面
        AppleUIAppMap, //回到carplay 苹果自家导航app的界面
        AppleUIAppPhone, //回到carplay电话界面
        AppleUIAppMusic, //回到carplay自家音乐app的界面
        AppleUIAppNowPlaying //回到carplay正在播放界面
    };

    enum LinkType
    {
        CARPLAY = 0x00,
        CARPLAY_WL = 0x07
    };

    enum TelButton
    {
        CallAccept = 2,
        CallDrop = 3
    };

    enum MediaButton
    {
        MediaNone = 0,
        MediaPlay,
        MediaPause,
        MediaPlayPause,
        MediaNext,
        MediaPrevious
    };

    SdCarplay(ICarplayCallbacks *pcbs);
    ~SdCarplay();

    void setValue(const char *key, int value, bool save = false);
    void setValue(const char *key, const char *value, bool save = false);
    int getIntValue(const char *key);
    const char *getStringValue(const char *key);

	int init();

    /* *
     * @brief 启动carplay
	 * @param type 0为有线,7为无线
	 * @param initialmode 设置carplay的初始启动模式
     * */
    int start(LinkType type, InitialMode initialmode);

	//强制停止carplay,一般情况(比如从车机拔苹果手机)不需要调用,仅在无线和有线相互切换的情况下用
    void stop();

    /* *
     * @brief carplay切换声音
     * @param release
     *         true: 失去音频焦点
     *         false: 获取音频焦点
     * */
    void setCarplayAudioMode(bool release);

    
    //获取carplay的当前状态
    CarplayState getCarplayState(void);

    //发送单点触摸坐标
    void sendSingleTouchscreen(unsigned short x, unsigned short y, bool pressed);

    //发送多点触摸坐标 idx0=0表示第一个点, idx1= 1表示第二个点
    void sendMulPtrTouchscreen(unsigned char idx0, unsigned short x0, unsigned short y0, bool pressed0, unsigned char idx1, unsigned short x1, unsigned short y1, bool pressed1);

    //发送电话按键
    void sendTelephoneButton(TelButton button, bool pressed);

    //发送媒体按键
    void sendMediaButton(MediaButton button, bool pressed);

    /* *
     * @brief 发送Siri按键
     * @param pressed true 为按下,启动siri
     *                false 为释放,停止siri
     * */
    void sendSiriButton(bool pressed);

    //发送knob的信息
    void sendKnobUpdate(char 	selectButtonPressed,
                        char 	homeButtonPressed,
                        char 	backButtonPressed,
                        double	x,
                        double	y,
                        char	wheelPositionRelative);

    //强制手机发送关键帧
    void forceKeyFrame(void);

    //回到carplay界面 @see AppleUIApp
    void requestUI(AppleUIApp app);

    /* *
     * @brief 设置进入夜间模式
     * @param enter true 进入夜间模式
     *              false 退出夜间模式
     * */
    void setNightMode(bool enter);

    void changeModes(CarplayTransferType 		inScreenType,
                            CarplayTransferPriority		inScreenPriority,
                            CarplayConstraint			inScreenTake,
                            CarplayConstraint			inScreenBorrow,
                            CarplayTransferType 		inAudioType,
                            CarplayTransferPriority		inAudioPriority,
                            CarplayConstraint			inAudioTake,
                            CarplayConstraint			inAudioBorrow,
                            CarplayTriState				inPhone,
                            CarplaySpeechMode			inSpeech,
                            CarplayTriState				inTurnByTurn);

	/* *
     * @brief 获取carplay送过来的音频数据,然后送到声卡播放
     * @param 		handle 该路音频流操作句柄
     * @param 		buffer 数据缓存
     * @param 		len	数据缓存大小
     * @param 		frames	音频数据帧大小 frames = len / (bits / 8 * channels)
     * @timestamp	timestamp 播放时间戳
     * */
	void playStream(int handle, void *buffer, int len, int frames, unsigned long long timestamp);
	
	/* *
     * @brief 从声卡获取录音数据,然后发给carplay
     * @param 		handle 该路音频流操作句柄
     * @param 		buffer 数据缓存
     * @param 		len	数据缓存大小
     * @param 		frames	音频数据帧大小 frames = len / (bits / 8 * channels)
     * @timestamp	timestamp 播放时间戳
     * */
	void recordStream(int handle, void *buffer, int len, int frames, unsigned long long timestamp);	

    void setBtAddr(char mac[6]);
	
	int readIap2DataProc(char *buf, int len);

    void setEncryptText(std::string &encryptText);

    std::string rsaPubEncrypt(const std::string &clearText, const std::string &pubKey);

    //void getAppleDeviceIpAddr(char *addr);
	
    friend class CarplayCallbacksPriv;
protected:

private:
    void setCarplayState(CarplayState state);

    LinkType                        mType;
    CarplayState                    mCarplayState;
    void                            *mAirPlayModeState;
    ICarplayCallbacks               *mCallbacks;
};

#endif
